
// ==UserScript==
// @name        xp1024 post viewer
// @name:zh-cn  xp1024 帖子预览器

// @description    xp1024 帖子预览器

// @description:zh-cn xp1024 帖子预览器
// @version     1.0
// @author      DaTree
// @namespace   none

// @match       *://*/*
// @run-at      document-end
// @grant       GM_registerMenuCommand
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @grant       GM_download
// @grant       GM_xmlhttpRequest
// @grant       GM_addStyle
// @grant       GM_getResourceText
// @grant       GM.getResourceText
// @resource ViewerJs https://cdn.jsdelivr.net/npm/viewerjs@1.11.6/dist/viewer.min.js
// @resource ViewerJsCss https://cdn.jsdelivr.net/npm/viewerjs@1.11.6/dist/viewer.min.css
// @license     MIT
// @icon         
// ==/UserScript==


(() => {
  "use strict"
  const ViewerJs = GM_getResourceText("ViewerJs");
  const ViewerJsCss = GM_getResourceText("ViewerJsCss");

  const ViewerStyle = document.createElement("style");
  ViewerStyle.id = "ViewerStyle";
  ViewerStyle.type = "text/css";
  ViewerStyle.innerHTML = ViewerJsCss;
  document.head.appendChild(ViewerStyle);

  const ViewerScript = document.createElement("script");
  ViewerScript.id = "ViewerScript";
  ViewerScript.type = "text/javascript";
  ViewerScript.innerHTML = ViewerJs;
  document.body.appendChild(ViewerScript);
  const localCacheHost = "http://localhost:44444";


  /**
   * 简单版线程池，只实现限制最大线程数量的功能。
   * 不实现 最小线程存活等功能。（在javascript中也没意义）
   */
  class ThreadPool {
    constructor(maxConcurrentTasks) {
      this.maxConcurrentTasks = maxConcurrentTasks;
      this.taskQueue = [];
      this.runningTasks = [];
      this.run = false
      this.newTaskId = 1000
    }

    start () {
      this.run = true
      this.executeTasks()
    }

    stop () {
      this.run = false
    }



    /**
     * 添加任务
     * @param {Function(complete)} taskFunction 该函数 会像你传递一个 complete 方法，需要在你的异步执行完成时调用它。
     * @param {*} taskId
     * @returns
     */
    addTask (taskFunction, taskId) {
      if (taskId == null) {
        taskId = this.newTaskId++
      }
      const task = () => {
        return new Promise((resolve) => {
          taskFunction(resolve)
        })
      }
      this.taskQueue.push({
        taskId,
        task
      });
      this.executeTasks();
    }
    /**
     * 执行任务
     */
    executeTasks () {
      while (this.run && this.taskQueue.length > 0 && this.runningTasks.length < this.maxConcurrentTasks) {
        const t = this.taskQueue.shift();
        this.runningTasks.push(t);
        t.task().then(() => {
          this.removeRunningTask(t);
        }).catch(() => {
          this.removeRunningTask(t);
        })
      }
    }
    /**
     * 移除任务
     * @param {*} task
     */
    removeRunningTask (task) {
      const index = this.runningTasks.indexOf(task);
      if (index !== -1) {
        this.runningTasks.splice(index, 1);
      }
      this.executeTasks();
    }
  }




  const utils = {
    /**
     * 参数处理
     * @param {*} params  参数
     */
    tansParams (params) {
      let result = "";
      for (const propName of Object.keys(params)) {
        const value = params[propName];
        var part = encodeURIComponent(propName) + "=";
        if (value !== null && value !== "" && typeof value !== "undefined") {
          if (typeof value === "object") {
            for (const key of Object.keys(value)) {
              if (
                value[key] !== null &&
                value[key] !== "" &&
                typeof value[key] !== "undefined"
              ) {
                let params = propName + "[" + key + "]";
                var subPart = encodeURIComponent(params) + "=";
                result += subPart + encodeURIComponent(value[key]) + "&";
              }
            }
          } else {
            result += part + encodeURIComponent(value) + "&";
          }
        }
      }
      return result;
    },
    wait (func, timespan = 100, timeoutCount = 500) {
      let waitIndex = 0;
      if (!window.__waitId__) {
        window.__waitId__ = 10000;
      }
      const waitId = ++window.__waitId__
      return new Promise((resolve, reject) => {
        const timer = setInterval(() => {
          waitIndex++;
          // console.log(`wait_id:${waitId},wait:${waitIndex}...`)
          if (func()) {
            clearInterval(timer);
            resolve();
          }
          if (waitIndex > timeoutCount) {
            clearInterval(timer);
            console.error(`wait_id:${waitId},wait:timerout!!!`)
            reject();
          }
        }, timespan);
      })
    },
    parseHTMLDOM (htmlString) {
      // 使用DOMParser来解析字符串
      var parser = new DOMParser();
      var doc = parser.parseFromString(htmlString, "text/html");
      return doc;
    },
    storage: {
      set (key, value) {
        GM_setValue(key, value);
      },
      get (key) {
        if (!GM_getValue(key)) {
          GM_setValue(key, null)
        }
        return GM_getValue(key)
      },
      delete (key) {
        GM_deleteValue(key);
      }
    }
  }
  const request = {
    send (config) {
      config.method = config.method ? config.method.toUpperCase() : "GET";
      // get请求映射params参数
      if (config.method === "GET" && config.params) {
        let url = config.url + "?" + utils.tansParams(config.params);
        url = url.slice(0, -1);
        config.params = {};
        config.url = url;
      }
      config.headers = config.headers ? config.headers : {
        "Content-Type": "application/json"
      }
      return new Promise((resolve, reject) => {

        GM_xmlhttpRequest({
          method: config.method,
          url: config.url,
          headers: config.headers,
          data: JSON.stringify(config.data),
          onload: function (response) {
            resolve(response.responseText);
          },
          // onreadystatechange (readyState) {
          //   console.log(config)
          //   console.log(readyState)
          // },
          onerror (e) {
            reject(e);
          }
        });
      });
    },

    get (config) {
      config.method = "GET"
      return this.send(config);
    },
    post (config) {
      config.method = "POST"
      return this.send(config);
    }
  }


  const api = {
    getPostsDetailHtml (url) {
      return new Promise(async (resolve, reject) => {
        let urlNotOk = true;
        while (urlNotOk) {
          try {
            const res = await request.get({
              url: url,
              method: "get",
              headers: {
                "Content-Type": "text/html"
              }
            })
            resolve(res);
            urlNotOk = false;
          } catch (error) {

          }
        }
      });


      // return ;
    }
  }
  let ViewerJsInstance = null;
  const icons = {
    backend: `<svg t="1719276744606" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6916" width="200" height="200"><path d="M658.724571 426.422857h-294.034285c-24.283429 0-43.995429-20.114286-43.995429-44.909714V81.554286c0-24.795429 19.748571-44.909714 44.032-44.909715h293.997714c24.283429 0 43.995429 20.114286 43.995429 44.909715v299.995428c0 24.795429-19.712 44.909714-43.995429 44.909715z m-274.029714-65.316571h254.025143V101.924571h-254.025143v259.181715zM928.548571 623.177143h-64v-65.718857a0.219429 0.219429 0 0 0-0.146285-0.146286H162.377143v66.450286H98.377143V555.885714c0-35.254857 28.013714-63.853714 62.573714-63.890285h703.414857c35.401143 0.036571 64.109714 29.330286 64.146286 65.462857v65.682285z" fill="#1296db" p-id="6917"></path><path d="M479.707429 408.32h64v214.784h-64z" fill="#1296db" p-id="6918"></path><path d="M0 623.104m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6919"></path><path d="M0 753.92m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6920"></path><path d="M383.670857 623.104m32.694857 0l190.646857 0q32.694857 0 32.694858 32.694857l0 0q0 32.694857-32.694858 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6921"></path><path d="M383.670857 753.188571m32.694857 0l190.646857 0q32.694857 0 32.694858 32.694858l0 0q0 32.694857-32.694858 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694858Z" fill="#1296db" p-id="6922"></path><path d="M767.122286 623.104m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6923"></path><path d="M767.122286 753.993143m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6924"></path><path d="M0 884.589714m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694858l-190.646857 0q-32.694857 0-32.694857-32.694858l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6925"></path><path d="M767.122286 884.699429m32.694857 0l190.646857 0q32.694857 0 32.694857 32.694857l0 0q0 32.694857-32.694857 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6926"></path><path d="M383.670857 884.699429m32.694857 0l190.646857 0q32.694857 0 32.694858 32.694857l0 0q0 32.694857-32.694858 32.694857l-190.646857 0q-32.694857 0-32.694857-32.694857l0 0q0-32.694857 32.694857-32.694857Z" fill="#1296db" p-id="6927"></path></svg>`,
    waterfall: `<svg t="1715842985527" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12474" width="200" height="200"><path d="M563.2 153.6H460.8c-28.672 0-51.2 22.528-51.2 51.2v256c0 28.672 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-22.528 51.2-51.2V204.8c0-28.672-23.552-51.2-51.2-51.2z m0 307.2H460.8c-1.024 0 0 0 0 0V204.8h102.4c1.024 0 0 0 0 0v256zM819.2 665.6H716.8c-28.672 0-51.2 23.552-51.2 51.2v102.4c0 28.672 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-23.552 51.2-51.2V716.8c0-28.672-23.552-51.2-51.2-51.2z m0 153.6H716.8V716.8h102.4v102.4zM819.2 153.6H716.8c-28.672 0-51.2 22.528-51.2 51.2v358.4c0 28.672 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-22.528 51.2-51.2V204.8c0-28.672-23.552-51.2-51.2-51.2z m0 409.6H716.8V204.8h102.4v358.4zM307.2 409.6H204.8c-28.672 0-51.2 22.528-51.2 51.2v358.4c0 28.672 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-22.528 51.2-51.2V460.8c0-28.672-23.552-51.2-51.2-51.2z m0 409.6H204.8V460.8h102.4v358.4zM563.2 563.2H460.8c-28.672 0-51.2 22.528-51.2 51.2v204.8c0 27.648 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-22.528 51.2-51.2V614.4c0-27.648-23.552-51.2-51.2-51.2z m0 256H460.8V614.4h102.4v204.8zM307.2 153.6H204.8c-28.672 0-51.2 23.552-51.2 51.2v102.4c0 28.672 23.552 51.2 51.2 51.2h102.4c28.672 0 51.2-23.552 51.2-51.2V204.8c0-28.672-23.552-51.2-51.2-51.2z m0 153.6H204.8V204.8h102.4v102.4z" fill="#1296db" p-id="12475"></path></svg>`,
    viewerInstanceUpdate: `<svg t="1715560499246" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7863" width="200" height="200"><path d="M908.2 510.3c-1.7-1.7-3.5-3.4-5.2-5.1V64H58v793h441.2c8.5 11.9 18.1 23.2 28.6 33.7 50.8 50.8 118.4 78.8 190.2 78.8s139.4-28 190.2-78.8S987 772.4 987 700.5s-28-139.4-78.8-190.2z m-380.4 0c-4.5 4.5-8.9 9.2-13 14l-30.5-43.8 214.6-135.8 79.2 93.6c-19.5-4.4-39.6-6.7-60.1-6.7-71.9-0.1-139.4 27.9-190.2 78.7zM853 114v335.3L734.2 309l-1.1-1.2c-14.9-15.5-40.8-18.4-59.1-6.7L455.7 439.3l-34.8-50.1c-6.5-9.8-16.5-16.6-28.1-19.1-11.8-2.5-23.8-0.3-33.9 6.2L108 539V114h745zM108 807V598.6l274-177.7 102 146.7c-22.8 40.1-35 85.5-35 132.9 0 37.2 7.5 73.3 21.8 106.5H108z m610 112.5c-120.8 0-219-98.2-219-219s98.2-219 219-219c52.7 0 101.1 18.7 139 49.9l1.9 2.3 0.4-0.3c47.5 40.2 77.7 100.2 77.7 167.2 0 120.7-98.2 218.9-219 218.9z" p-id="7864" fill="#1296db"></path><path d="M247 370c62.9 0 114-51.1 114-114s-51.1-114-114-114-114 51.1-114 114 51.1 114 114 114z m0-178c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zM843.6 661.3c-10.9 1.9-18.2 12.2-16.3 23.1 1.1 6.4 1.7 12.9 1.7 19.4 0 62.2-50.6 112.9-112.9 112.9s-112.9-50.6-112.9-112.9S653.9 591 716.1 591c23.4 0 45.9 7.1 65 20.6 1 0.7 2 1.2 3 1.7l-27.2 3.1c-9.9 1.1-17 10-15.9 19.9 1 9.2 8.8 16 17.9 16 0.7 0 1.4 0 2-0.1l56.6-6.4c6.8-0.5 13-3.6 17.7-8.6 4.8-5.3 7.2-12.1 6.9-19.1l-2.8-58.6c-0.5-9.9-8.9-17.6-18.8-17.1s-17.6 8.9-17.1 18.8l0.8 17.9-0.1-0.1c-25.9-18.3-56.3-27.9-88.1-27.9-84.3 0-152.9 68.6-152.9 152.9 0 84.3 68.6 152.9 152.9 152.9 84.3 0 152.9-68.6 152.9-152.9 0-8.8-0.8-17.7-2.3-26.3-1.7-11-12.1-18.3-23-16.4z m-37.8-50.5l-0.8 0.1c0.3-0.2 0.5-0.4 0.7-0.6l0.1 0.5z" p-id="7865" fill="#1296db"></path></svg>`,
    loading: ``,
    reParse: `<svg t="1715150139474" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1677" width="200" height="200"><path d="M277.9 520.4c0 124.4 100.9 225.3 225.3 225.3s225.3-100.9 225.3-225.3-100.9-225.3-225.3-225.3-225.3 100.8-225.3 225.3z m0 0" fill="#E9EAEB" p-id="1678"></path><path d="M410.3 264c78.7-3.2 154.3 31.1 203.8 92.4l-76.3 48.1 277.3 116.1V225.8L743.2 275c-65.3-69.7-157.4-108-252.9-105.1-122.8 4.7-232.8 77.4-285.1 188.6l11.8 8.1c45.4-61.9 116.6-99.7 193.3-102.6z m0 0" fill="#A3D4FF" p-id="1679"></path><path d="M832.5 546.5L500.4 407.7l87.1-55.1c-47.9-49.6-115.2-75.6-184-70.9-68.8 4.7-132 39.5-172.7 95.2l-9.9 13.7-37.6-26.6 6.2-13.3C237.3 249 331.5 177 442 157.4c110.6-19.6 223.7 15.8 303.4 94.9l87.1-59.6v353.8zM575.3 401.4l222.5 92.9V258.6l-57 39-10.2-10.7c-61.7-66.2-149-102.6-239.4-99.8-85.7 3-166.4 41.4-222.9 105.9 41.7-28.5 90.7-44.6 141.3-46.4 84.1-3.4 164.8 33.3 217.7 98.8l12.3 15.2-64.3 40.8z m0 0" fill="#2A5082" p-id="1680"></path><path d="M789.5 654c-45.9 62.8-118.3 100.7-196 102.7s-152-32.2-201-92.5l76.4-48.1L191.3 503v294.6l72.1-52c65.3 69.7 157.4 108 252.9 105.1 122.9-4.6 232.9-77.4 285.2-188.6l-12-8.1z m0 0" fill="#A3D4FF" p-id="1681"></path><path d="M504.4 868.4c-90.9-0.4-178-36.3-242.8-100L174 831.5V477.3l332.6 135.5-87.6 55.1c45.9 48.1 110.3 74.1 176.7 71.3 71.4-2.6 137.8-37.8 179.9-95.5l10.1-13.7 37.6 26.6-6.2 13.2c-55 117.1-170.9 193.6-300.2 198.3-4.2 0.2-8.4 0.3-12.5 0.3zM265.7 722.8l10.4 11c61.7 66.2 149 102.6 239.4 99.8 85.7-3.1 166.3-41.4 222.7-106C623 806 467 783.2 379 675.2L366.7 660l64.4-40.9-222.5-90.3v235l57.1-41z m0 0" fill="#2A5082" p-id="1682"></path><path d="M1020.1 567.7l-34.7-3.8c1.4-12.7 2.2-23.3 2.6-33.2 5.1-126.3-40.2-249.5-125.9-342.5S657.2 40.2 530.9 35.1L532.6 0.6C814.7 12 1034.2 250 1022.9 532.1c-0.4 10.7-1.2 22.1-2.8 35.6zM59.2 749C-6.7 623.4-17.5 476.1 29.4 342.2 76.3 208.4 176.7 100 306.6 43.1L320.5 75C199.4 128 105.8 229 62.1 353.8 18.3 478.6 28.4 615.9 89.9 733l-30.7 16z m452.6 273.8c-6.8 0-13.7-0.1-20.5-0.4-101.8-3.8-200.1-38.2-282.2-98.5l20.5-27.9c106.5 78.3 240.8 108.8 370.7 84.3 129.9-24.5 243.8-101.9 314.5-213.6l29 18.6c-94 147.5-256.9 237.1-432 237.5z m0 0" fill="#BCC0C4" p-id="1683"></path></svg>`,
    eye: `<svg t="1715150073293" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1518" width="200" height="200"><path d="M158.8 478c0 199 161.4 360.4 360.4 360.4S879.6 677 879.6 478 718.3 117.6 519.2 117.6 158.8 279 158.8 478z m0 0" fill="#E9EAEB" p-id="1519"></path><path d="M288.2 97.1l-17.1-28.8c153-90.6 343.2-90.6 496.2 0l-17.1 28.8c-142.5-84.3-319.6-84.3-462 0zM397.7 128l32.4-8.7 13.1 48.9-32.4 8.7-13.1-48.9zM234.9 234.4l23.7-23.7 35.8 35.8-23.7 23.7-35.8-35.8z m-87.8 173.7l8.7-32.4 48.9 13.1-8.7 32.4-48.9-13.1z m2.1 161.8l48.9-13.1 8.7 32.4-48.9 13.1-8.7-32.4z m91.5 171.5l35.8-35.8 23.7 23.7-35.8 35.8-23.7-23.7z m494.9-17.9l23.7-23.7 35.8 35.8-23.7 23.7-35.8-35.8z m89.7-142.2l8.7-32.4 48.9 13.1-8.7 32.4-48.9-13.1z m-2.2-200.5l48.9-13.1 8.7 32.4-48.9 13.1-8.7-32.4z m-93.4-140.1l35.8-35.8 23.7 23.7-35.8 35.8-23.7-23.7z m-150.9-74.6l13.1-48.9 32.4 8.7-13.1 48.9-32.4-8.7z m174.4 742.1l-16.7-29.4c139.5-80.2 226.3-228 228.6-388.9l33.5 0.4c-2.3 172.8-95.5 331.6-245.4 417.9z m-483 0C120.5 822 27.2 663.3 24.7 490.6l33.5-0.4c2.2 160.9 89.1 308.7 228.6 388.9l-16.6 29.1z m0 0" fill="#BCC0C4" p-id="1520"></path><path d="M530.8 235.2c-100.2-5-193.2 52.2-234 143.9-40.7 91.7-20.8 199.1 50.1 270.1C376.2 677.8 393 717 393.4 758v30.1h251.3V758c-0.2-40 15.7-78.5 44.1-106.7 46.8-45.3 73.3-107.7 73.6-172.8-0.7-129.6-102.2-236.2-231.6-243.3z m0 0" fill="#FFFFFF" p-id="1521"></path><path d="M661.7 788.1h-33.5V758c-0.1-44.5 17.7-87.2 49.4-118.6 43.5-42.2 68-100.3 68-160.9C744.6 358 650.3 258.8 530 252c-93.2-4.5-179.7 48.8-217.6 134.1-37.9 85.3-19.4 185.2 46.5 251.3a170.6 170.6 0 0 1 51.5 120.7v30.1h-33.7V758c-0.4-36.6-15.3-71.5-41.6-97-75.6-75.9-96.8-190.6-53.4-288.5 43.5-98 142.7-159.2 249.7-154 138.3 7.8 246.6 121.6 247.6 260 0.1 69.6-28.1 136.3-78 184.8-25.2 25-39.4 59.1-39.3 94.7v30.1z m0 0" fill="#2A5082" p-id="1522"></path><path d="M481.8 639.7c-56-19.7-82.8-86.2-73.5-121.7 25.7-95 121.4-104.2 163-173.3 61.1 42.5 100.2 127 71.6 205.9-19.3 53-89.2 73.6-117.7 79.4" fill="#A3D4FF" p-id="1523"></path><path d="M476.2 655.5c-61.8-22.1-96.4-95.6-83.9-141.9 16.4-61.1 59.6-90.6 97.7-116.7 26.4-18.1 51.5-35.1 67-61l9.3-15.3 14.7 10.2C644.4 375 691.3 466.4 658.7 556c-23.2 63.3-105.2 84.9-129.7 90.1l-6.8-32.8c14.7-3 87.4-20.5 105.1-68.8 24.6-67.4-6.3-136.4-52.1-175.9-18.6 23.5-42.7 39.9-66.2 56-36.8 25-71.1 48.6-84.3 97.7-7.4 28.6 15.8 85.1 62.7 101.6l-11.2 31.6z m0 0" fill="#2A5082" p-id="1524"></path><path d="M479 726.7c-37.2-105.4 7.4-190.1 43.2-258.2 6.2-12 12.2-23.1 17.5-34.1l30.2 14.7c-5.6 11.5-11.6 22.9-18 35.1-34.5 65.5-73.6 139.7-41.3 231.4L479 726.7zM372.6 409.3l-30.9-13.5c24.1-55.1 73.5-95 132.4-106.9l6.7 32.9c-48.1 9.8-88.5 42.5-108.2 87.5zM360 469.6h-33.5c0-12.4 1.2-24.7 3.7-36.8l32.9 6.7c-2.1 9.9-3.1 20-3.1 30.1z m191.3 553.2h-64.2l-33.5-33.5H427v-33.5h40.5l33.5 33.5h36.4l33.5-33.5h40.5v33.5h-26.5l-33.6 33.5zM376.8 821.6h284.9v33.5H376.8v-33.5z m0 67.1h284.9v33.5H376.8v-33.5z m0 0" fill="#2A5082" p-id="1525"></path></svg>`,
    download: `<svg t="1715150047369" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9830" width="200" height="200"><path d="M148 641.7c0 136.1 72.6 261.9 190.5 330 117.9 68.1 263.1 68.1 381 0S910 777.9 910 641.7c0-136.1-72.6-261.9-190.5-330-117.9-68.1-263.1-68.1-381 0C220.6 379.8 148 505.6 148 641.7z m0 0" fill="#EDEDED" p-id="9831"></path><path d="M391.6 208.7v190.5H251.8L529 711l277.1-311.8H667.6V208.7h-276z m0 0" fill="#A3D4FF" p-id="9832"></path><path d="M529 737L213.4 381.9h161V191.4h310.5v190.5h159.8L529 737zM290.7 416.9l238.3 268 238.3-268.1h-117V226H409v190.5l-118.3 0.4z m0 0" fill="#2A5082" p-id="9833"></path><path d="M391.6 52.8h275.9v86.6H391.6z" fill="#A3D4FF" p-id="9834"></path><path d="M684.8 156.8H374.3V35.5h310.5v121.3zM409 122.1h241.3V70H409v52.1z m0 0" fill="#2A5082" p-id="9835"></path><path d="M910 745.6v173.2H148V745.6h103.9v69.2h554.2v-69.2H910z m0 0" fill="#FFFFFF" p-id="9836"></path><path d="M927.4 936.1H130.6V728.2h138.6v69.2h519.6v-69.2h138.6v207.9z m-762.2-34.7h727.4V763.2h-69.2v69.2H234.6v-69.2h-69.2l-0.2 138.2z m0 0" fill="#2A5082" p-id="9837"></path><path d="M96 364.6h34.6v155.8H96V364.6zM754.2 0.9h34.6V278h-34.6V0.9zM96 295.3h34.6V330H96v-34.7z m0-69.3h34.6v34.6H96V226z m0 0" fill="#BCC0C4" p-id="9838"></path></svg>`
  }
  let showImage = false;
  const pool = new ThreadPool(30)
  pool.start()
  const service = {
    scrollPercent: 0,
    waitDownload: utils.storage.get("waitDownload") != null ? JSON.parse(utils.storage.get("waitDownload")) : true,
    async init () {
      await utils.wait(() => {
        return document.readyState == 'interactive' || document.readyState == 'complete'
      });
      if (!document.querySelector("#main")) {
        return
      }
      if (this.waitDownload == false) {

        document.querySelector("#main").classList.add("backend");

      }
      this.initCSS();
      this.setWaterFallStyle();
      this.main();
      this.clearKeyCodeEvent();
    },
    async main () {
      const groupDoms = document.querySelectorAll("#breadCrumb font a");
      let groupName = ""
      if (groupDoms.length > 0) {
        groupName = groupDoms[groupDoms.length - 1].innerText;
      }
      const postDoms = document.querySelectorAll(".tr3 td h3 a[href][id^=a_ajax]")
      const me = this;
      me.addToolBar();
      for (let index = 0; index < postDoms.length; index++) {
        const postDom = postDoms[index];
        let isTop = false;
        try {
          isTop = postDom.parentElement.parentElement.innerHTML.includes("置顶")
        } catch (e) {
        }
        if (isTop) {
          continue;
        }
        const parentDom = postDom.parentNode;
        await this.getPostImageAndDownloadUrl(postDom, postDom.baseURI + postDom.getAttribute("href"), groupName);
        const reParseBtn = utils.parseHTMLDOM(icons.reParse).body.firstChild;
        reParseBtn.classList.add("view-reparse-btn");
        reParseBtn.addEventListener("click", () => {
          me.getPostImageAndDownloadUrl(postDom, postDom.baseURI + postDom.getAttribute("href"), groupName);
        });
        parentDom.appendChild(reParseBtn);

        parentDom.parentNode.classList.add("view-warp-container")

        const viewBtn = utils.parseHTMLDOM(icons.eye).body.firstChild;
        viewBtn.classList.add("view-btn");


        viewBtn.setAttribute("show", "0");

        viewBtn.addEventListener("click", () => {
          viewBtn.setAttribute("show", viewBtn.getAttribute("show") == "0" ? "1" : 0);
          if (viewBtn.getAttribute("show") == "0") {
            parentDom.parentNode.classList.remove("show");
          } else {
            parentDom.parentNode.classList.add("show");
          }
        });

        viewBtn.addEventListener("mouseover", () => {
          if (!parentDom.parentNode.classList.contains("show")) {
            parentDom.parentNode.classList.add("show");
          }
        });

        viewBtn.addEventListener("mouseout", () => {
          if (parentDom.parentNode.classList.contains("show") && viewBtn.getAttribute("show") == "0") {
            parentDom.parentNode.classList.remove("show");
          }
        });
        parentDom.appendChild(viewBtn);
        // if (index > 5) {
        //   break;
        // }
        //break;

      }
    },
    clearKeyCodeEvent () {
      document.onkeydown = null;
    },
    setWaterFallStyle (count) {
      count = count || utils.storage.get("waterFallConfig") || 3;
      utils.storage.set("waterFallConfig", count)
      // 读取瀑布流配置
      const mainDiv = document.querySelector("#main") || document.querySelector("#read_tpc")
      if (mainDiv) {
        for (let i = 1; i <= 9; i++) {
          mainDiv.classList.remove(`waterfall-${i}`);
        }
        mainDiv.classList.add(`waterfall-${count}`);
      }
    },

    initCSS () {
      let css = `
        .prevImage{
          width:100%;
          height:auto;
          object-fit: contain;
          position: relative;
        }
        .glass-effect::before {
          content: " ";
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: transparent;
          backdrop-filter: blur(17px);
          box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
          position:absolute;
          z-index:10;
          pointer-events:none;
          padding-left: 2px;
          padding-bottom: 2px;
        }
        .glass-effect {
          position:relative;
          margin-bottom: 10px;
          break-inside:avoid;
        }

        .glass-effect:hover::before{
          background-color:none;
          backdrop-filter:none;
        }
        .backend .view-warp{
          display:none;
        }
        .view-warp-container {
          position: relative;
          height: 80px;
          vertical-align: top;
          overflow: hidden;
          z-index: 1;
        }
        .view-warp-container:hover {
          overflow: unset;
        }
        .view-warp-container.show .glass-effect::before {
          background-color:none;
          backdrop-filter:none;
        }
        .waterfall-1 .view-warp{
          column-count: 1;
        }
        .waterfall-2 .view-warp{
          column-count: 2;
        }
        .waterfall-3 .view-warp{
          column-count: 3;
        }
        .waterfall-4 .view-warp{
          column-count: 4;
        }
        .waterfall-5 .view-warp{
          column-count: 5;
        }
        .waterfall-6 .view-warp{
          column-count: 6;
        }
        .waterfall-7 .view-warp{
          column-count: 7;
        }
        .waterfall-8 .view-warp{
          column-count: 8;
        }
        .waterfall-9 .view-warp{
          column-count: 9;
        }
        .view-warp {
          width: 100%;
          background: #e3e3e3;
          left: 0;
          top: 36px;
          min-height: 50px;
          padding-bottom: 0px;
          z-index: 1000;
          /*display: grid;*/
          /*grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));*/
          /*grid-auto-rows: 100px;*/
         /* grid-gap: 10px;*/
         /* padding: 0 10px;*/
        }
        .view-warp:hover .glass-effect{
          visibility: visible;
        }


        .masonry-item {
            position: relative;
            border-radius: 6px;
            overflow: hidden;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            transition: transform 0.3s ease;
        }

        .masonry-item img {
            display: block;
            width: 100%;
            height: 100%;
            object-fit: cover;
        }




        .prev-download-url{
          float:left;
          color:blue;
          width:100%;
        }
        .view-reparse-btn{
          float: left;
          color: red;
          font-size: 1rem;
          cursor: pointer;
          margin-right: 5px;
          width: 23px;
          height: 23px;
        }
        .view-btn{
          float: left;
          color: red;
          font-size: 1rem;
          cursor: pointer;
          margin-right: 5px;
          width: 23px;
          height: 23px;
        }
        .view-prev-iframe{
          width:100%;
          height:30px;
          border:0;
        }
        .view-tool-bar{
          position:fixed;
          z-index:100;
          left:5px;
          top:49%;
          width:32px;
          display:flex;
          flex-direction: column;
        }
        .view-tool-bar .view-btn{
          width: 32px;
          height: 32px;
        }
        .view-tool-bar .pic-update-btn{
          width: 32px;
          height: 32px;
          cursor: pointer;
        }
        .view-tool-bar .layout{
          width: 32px;
          height: 32px;
          cursor: pointer;
          position:relative;
        }
        .view-tool-bar .layout .grid-container {
          display: none;
          grid-template-columns: repeat(3, 1fr);
          grid-template-rows: repeat(3, 1fr);
          gap: 0;
          position:absolute;
          left:100%;
          top:0;
          width:100px;
          height:100px;
         }
        .view-tool-bar .layout .grid-container.show{
          display: grid;
        }

        .view-tool-bar .layout .grid-container .grid-item {
          border: 1px solid #1296db;
          display: flex;
          color:#000;
          justify-content: center;
          align-items: center;
        }
        `
      GM_addStyle(css)
    },

    addToolBar () {
      const me = this;



      const toolBar = document.createElement("div");
      toolBar.classList.add("view-tool-bar");
      const viewBtn = utils.parseHTMLDOM(icons.eye).body.firstChild;
      viewBtn.classList.add("view-btn");
      viewBtn.addEventListener("mouseover", () => {
        document.querySelector("#main").classList.add("view-warp-container");
        document.querySelector("#main").classList.add("show");
      });
      viewBtn.addEventListener("mouseout", () => {
        if (!showImage) {
          document.querySelector("#main").classList.remove("view-warp-container");
          document.querySelector("#main").classList.remove("show");
        }
      });
      viewBtn.addEventListener("click", () => {
        showImage = !showImage;
        if (showImage) {
          document.querySelector("#main").classList.add("view-warp-container");
          document.querySelector("#main").classList.add("show");
        } else {
          document.querySelector("#main").classList.remove("view-warp-container");
          document.querySelector("#main").classList.remove("show");
        }
      })
      toolBar.appendChild(viewBtn);
      const backendBtn = utils.parseHTMLDOM(icons.backend).body.firstChild;
      backendBtn.classList.add("view-btn");
      backendBtn.addEventListener("click", () => {
        me.waitDownload = !me.waitDownload
        utils.storage.set("waitDownload", JSON.stringify(me.waitDownload));
        if (me.waitDownload) {
          document.querySelector("#main").classList.remove("backend");
          alert("展示模式")
        } else {
          document.querySelector("#main").classList.add("backend");
          alert("后台模式")
        }
      });
      // const viewerInstanceUpdateBtn = utils.parseHTMLDOM(icons.viewerInstanceUpdate).body.firstChild;
      // viewerInstanceUpdateBtn.classList.add("pic-update-btn");
      // viewerInstanceUpdateBtn.addEventListener("click", () => {
      //   ViewerJsInstance.update();
      // });
      // toolBar.appendChild(viewerInstanceUpdateBtn);
      toolBar.appendChild(backendBtn);


      const viewerWaterFallBtnContainer = document.createElement("div");
      viewerWaterFallBtnContainer.classList.add("layout");

      const viewerWaterFallBtn = utils.parseHTMLDOM(icons.waterfall).body.firstChild;
      viewerWaterFallBtn.classList.add("layout");
      viewerWaterFallBtnContainer.appendChild(viewerWaterFallBtn);

      const gridContainer = document.createElement('div');
      gridContainer.classList.add("grid-container");
      viewerWaterFallBtn.appendChild(gridContainer);
      for (let index = 1; index <= 9; index++) {
        const layoutItem = document.createElement("div");
        layoutItem.classList.add("grid-item")
        layoutItem.innerText = index.toString();
        layoutItem.addEventListener("click", () => {
          // 记录滚动条比例
          service.scrollPercent = window.scrollY / document.body.clientHeight;
          me.setWaterFallStyle(index);
          //切换布局后跳转到记录的比例
          setTimeout(() => {
            window.scrollTo(0, document.body.clientHeight * service.scrollPercent);
          }, 100);

        });
        gridContainer.appendChild(layoutItem);
      }
      viewerWaterFallBtnContainer.addEventListener("mouseover", () => {
        gridContainer.classList.add("show")
      });
      viewerWaterFallBtnContainer.addEventListener("mouseout", () => {
        gridContainer.classList.remove("show")
      });
      viewerWaterFallBtnContainer.appendChild(gridContainer);
      toolBar.appendChild(viewerWaterFallBtnContainer);
      document.body.appendChild(toolBar);
    },
    parseServerFileInfo (postDom, fileUrl, index, groupName, imageDom, onImageLoad, onImageLoadError) {
      const me = this
      const postUrl = postDom.getAttribute("href");
      const postId = postUrl.substring(postUrl.lastIndexOf("/") + 1, postUrl.lastIndexOf("."));
      const postName = this.replaceDirName(postDom.innerText);
      const fileExt = fileUrl.substring(fileUrl.lastIndexOf("."));
      const fileName = `${index}${fileExt}`
      groupName = this.replaceDirName(groupName);
      const dirName = postId + "-" + postName;
      const requestUrl = `${localCacheHost}/file/getFileStreamAutoCache?` + utils.tansParams({
        fileUrl,
        groupName,
        dirName,
        fileName,
        waitDownload: me.waitDownload
      })
      imageDom.setAttribute("src", requestUrl);
      imageDom.setAttribute("data-src", requestUrl);
      imageDom.addEventListener("error", () => {
        imageDom.setAttribute("src", fileUrl);
        imageDom.setAttribute("data-src", fileUrl);
      });
      const tempImg = new Image();
      // 定义图像加载成功时的处理函数
      tempImg.onload = function (e) {
        onImageLoad(e);
      };

      // 定义图像加载失败时的处理函数
      tempImg.onerror = function (e) {
        onImageLoadError(e);
      };
      tempImg.src = requestUrl;
    },
    replaceDirName (str) {
      let result = str
      const replaeArray = ["\\", "/", ":", "*", "?", "\"", "<", ">", "|"]
      replaeArray.forEach(item => {
        result = result.replaceAll(item, "");
      })
      return result;
    },


    parseDownLoadAddressByIFrame (aDom, pDom) {
      const iframe = document.createElement("iframe");
      iframe.classList.add("view-prev-iframe");
      iframe.src = aDom.href;
      pDom.appendChild(iframe);
    },

    getPostImageAndDownloadUrl (aDom, url, groupName) {
      const me = this;
      return new Promise(async (resolve) => {
        const parentDom = aDom.parentNode.parentNode;
        // 移除旧元素
        parentDom.querySelectorAll(".view-warp").forEach(item => { item.remove() });
        parentDom.querySelectorAll(".prev-download-url").forEach(item => { item.remove() })
        parentDom.querySelectorAll(".view-prev-iframe").forEach(item => { item.remove() })
        const html = await api.getPostsDetailHtml(url);
        const dom = utils.parseHTMLDOM(html);
        const images = dom.querySelectorAll("#read_tpc img")
        const downloadDoms = dom.querySelectorAll("#read_tpc a[target^=_blank]")
        const warp = document.createElement("div");
        warp.classList.add("view-warp");
        parentDom.appendChild(warp);
        const posterViewer = new Viewer(warp, {
          url: "data-src"
        });
        for (let index = 0; index < images.length; index++) {
          const element = images[index];
          element.classList.add("prevImage");
          const div = document.createElement("div");
          div.classList.add("glass-effect");
          div.classList.add("masonry-item");

          pool.addTask((done) => {
            me.parseServerFileInfo(aDom, element.getAttribute("src"), index + 1, groupName, element, (e) => {
              //img success
              div.appendChild(element);
              const width = e.target.naturalWidth;
              const height = e.target.naturalHeight;
              const ratio = (width / height).toFixed(4); // 保留4位小数
              // 设置aspectRatio
              div.style.aspectRatio = ratio;

              posterViewer.update()
              done()
            }, () => {
              //img error
              div.appendChild(element);
              posterViewer.update()
              done();
            });
          })
          warp.appendChild(div);
          // break;
        }

        for (let index = 0; index < downloadDoms.length; index++) {
          const element = downloadDoms[index];
          element.classList.add("prev-download-url");

          // if (element.getAttribute("href").includes("b23dow")) {
          parentDom.appendChild(element);
          me.parseDownLoadAddressByIFrame(element, parentDom);
          // }
        }



        resolve();
      });
    }
  }
  service.init();
  /**
   * 详情页，本地快速浏览器，添加瀑布流视图
   */
  const serviceDetail = {
    async init () {
      await utils.wait(() => {
        return document.readyState == 'interactive' || document.readyState == 'complete'
      });
      const read_tpc = document.querySelector("#read_tpc");
      if (read_tpc) {
        ViewerJsInstance = new Viewer(read_tpc, {
          url: "data-src"
        });
        const groupDoms = document.querySelectorAll("#breadCrumb font a");
        let groupName = ""
        let postName = ""
        let postId = null
        if (groupDoms.length > 1) {
          groupName = groupDoms[groupDoms.length - 2].innerText;
          postName = groupDoms[groupDoms.length - 1].innerText;
          postId = groupDoms[groupDoms.length - 1].getAttribute("href").split("tid=")[1];
        }
        this.parseDetailDoms(postId, groupName, postName);
      }
    },
    parseServerFileInfo (postId, fileUrl, index, groupName, imageDom, postName) {
      postName = this.replaceDirName(postName);
      const fileExt = fileUrl.substring(fileUrl.lastIndexOf("."));
      const fileName = `${index}${fileExt}`
      groupName = this.replaceDirName(groupName);
      const dirName = postId + "-" + postName;
      const requestUrl = `${localCacheHost}/file/getFileStreamAutoCache?` + utils.tansParams({
        fileUrl,
        groupName,
        dirName,
        fileName
      })
      imageDom.setAttribute("src", requestUrl);
      imageDom.setAttribute("data-src", requestUrl);
      imageDom.addEventListener("error", () => {
        imageDom.setAttribute("src", fileUrl);
        imageDom.setAttribute("data-src", fileUrl);
      });
    },
    replaceDirName (str) {
      let result = str
      const replaeArray = ["\\", "/", ":", "*", "?", "\"", "<", ">", "|"]
      replaeArray.forEach(item => {
        result = result.replaceAll(item, "");
      })
      return result;
    },

    parseDetailDoms (postId, groupName, postName) {
      const me = this;
      const parentDom = document.querySelector("#read_tpc");
      const images = document.querySelectorAll("#read_tpc img")
      const downloadDoms = document.querySelectorAll("#read_tpc a[target^=_blank]")
      const warp = document.createElement("div");
      warp.classList.add("view-warp");
      parentDom.querySelectorAll("br").forEach(dom => {
        dom.remove();
      });
      parentDom.insertBefore(warp, parentDom.firstChild);
      for (let index = 0; index < images.length; index++) {
        const element = images[index];
        element.classList.add("prevImage");
        const div = document.createElement("div");
        div.classList.add("glass-effect");
        me.parseServerFileInfo(postId, element.getAttribute("src"), index + 1, groupName, element, postName);
        div.appendChild(element);
        warp.appendChild(div);
        // break;
      }
      ViewerJsInstance.update();

      for (let index = 0; index < downloadDoms.length; index++) {
        const element = downloadDoms[index];
        element.classList.add("prev-download-url");

        if (element.getAttribute("href").includes("b23dow")) {
          parentDom.appendChild(element);
          me.parseDownLoadAddressByIFrame(element, parentDom);
        }
      }

    },
    parseDownLoadAddressByIFrame (aDom, pDom) {
      const iframe = document.createElement("iframe");
      iframe.classList.add("view-prev-iframe");
      iframe.src = aDom.href;
      pDom.appendChild(iframe);
    }
  }
  serviceDetail.init();
})();